package wortubung.util;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

import javax.swing.*;
import java.awt.*;

import static wortubung.util.CommonUtils.*;

public class ToolBase implements Printable
{
	public static PrintStream out;
    public static PrintStream log = System.err;
    public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

    private static ToolBase singleton = null;

    public static ToolBase getSingleton() {
    	if (singleton == null)
    		new ToolBase();
    	return singleton;
    }

    static {
    	try {
    		// The keys to display UTF in Windows console:
    		//   1. chcp 65001
    		//   2. Use a TrueType font.
    		if (System.getProperty("os.name").startsWith("Windows"))
    			out = System.out;
    		else
    			out = new PrintStream(System.out, true, "UTF-8");
    	} catch(Exception e) {
    		e.printStackTrace();
    	}
    }

    protected void printHelp() {
        log.println("Usage: java " + getClass().getName() + " (option)* (wordlist_file_or_dir)*");
        log.println("Options include:");
    	for (String s : getCmdlineOptions())
    	    log.println("    " + s);
    	printHelpText();
    }

    public ToolBase() {
    	this(false);
    }

    public ToolBase(boolean isPrinting) {
    	this.isPrinting = isPrinting;
  	
    	if (singleton != null)
    		throw new RuntimeException("ToolBase has already been created with " + singleton.getClass().getName());
    	singleton = this;
    }

    protected void printHelpText() {
    }

    protected String[] inFilenames = EMPTY_STRING_ARRAY;
    protected PrintWriter pw;
	private boolean isPrinting = false;
	private boolean isEchoing = true;
	private int pageWidth = 100;
    protected boolean isHelp = false;

    protected String[] getCmdlineOptions() {
    	final String[] options = {};
    	return options;
    }

    protected void cmdlineOption(String option, String value) {
    }

    protected void init(String[] args) throws IOException {
    	ArrayList<String> infiles = new ArrayList<String>();
        for (String fname : args) {
            if (!fname.startsWith("-")) {
            	infiles.add(fname);
            } else {
                fname = fname.substring(1);
        		if (fname.startsWith("?")) {
        			isHelp = true;
        		    printHelp();
        		    return;
        		}
                int idx = fname.indexOf('=');
                if (idx == 0)
                    continue;
                else if (idx < 0)
                    cmdlineOption(fname, null);
                else
                    cmdlineOption(fname.substring(0, idx), fname.substring(idx+1));
            }
        }

        inFilenames = infiles.toArray(new String[infiles.size()]);
    }

    public void printLine() {
    	printLine(null);
    }

    public void printLine(String line, Object... params) {
    	printText(neverNull(line) + NL, params);
    }

    public void printText(String line, Object... params) {
        if (isNotEmpty(params))
            line = String.format(line, params);

        if (pw != null) {
            pw.print(line);
        } else if (jTextArea != null) {
        	jTextArea.append(line);
        } else {
            Console.print(line);
        }
    }

    public void openOutputFile(String fileName) throws IOException {
   		closeOutputFile();
   		if (isNotEmpty(fileName)) {
   			File f = new File(fileName);
   			File parent = f.getParentFile();
   			if (parent != null && !parent.mkdirs())
   				parent.mkdirs();
            pw = openFileToWrite(f, false);
            log.println("Opened " + fileName + " to write as " + FILE_ENCODING);
   		}
    }

    public void closeOutputFile() throws IOException {
        if (pw != null) {
           	pw.flush();
           	pw.close();
            pw = null;
        }
    }

    public void print(String msg) {
    	if (isPrinting)
    		printText(msg);
    	else if (isEchoing)
    		Console.print(msg);
    }
    
    public void println() {
    	if (isPrinting)
    		printLine();
    	else if (isEchoing)
    		Console.println("");
    }

    public void println(String msg) {
    	print(neverNull(msg));
    	println();
    }

    public void printf(String fmt, Object... vals) {
    	print(String.format(fmt, vals));
    }

    public void printfln(String fmt, Object... vals) {
    	println(String.format(fmt, vals));
    }

    public void error(Throwable t) {
    	StringBuilder sb = new StringBuilder();
    	getRelevantStackTrace(sb, t);
    	promptln(sb.append('\n').toString());
    }

    public void error(Object... msg) {
    	promptln(concat(msg));
    	promptln();
    }

    public boolean isPrinting() {
    	return this.isPrinting;
    }

    public void setPrinting(boolean printing) {
    	this.isPrinting = printing;
    }

    public boolean isEchoing() {
    	return this.isEchoing;
    }

    public void setEchoing(boolean Echoing) {
    	this.isEchoing = Echoing;
    }

    public void promptf(String fmt, Object... vals) {
    	if (vals.length > 0)
    		fmt = String.format(fmt, vals);
    	prompt(fmt);
    }

    public void promptfln(String fmt, Object... vals) {
    	promptf(fmt, vals);
    	promptln();
    }

    public void promptln(Object... msg) {
    	promptln(concat(msg));
    }

    public void promptln(String msg) {
    	Console.println(msg);
    }

    public void promptln() {
    	Console.println("");
    }

    public void prompt(Object... msg) {
    	Console.print(concat(msg));
    }

    public int getPageWidth() { return pageWidth; }

    public void setPageWidth(int width) { this.pageWidth = width; }

    public void printToPageWidth(Object[] values, int sepSize) {
    	printToPageWidth(Arrays.asList(values), sepSize);
    }

    public void printToPageWidth(Collection<Object> values, int sepSize) {
    	int itemWidth = 2;
    	for (Object v : values) {
    		int w = getWidth(v);
    		if (w > itemWidth)
    			itemWidth = w;
    	}
    	int itemsPerLine = getPageWidth() / (itemWidth + sepSize);
    	if (getPageWidth() - itemsPerLine * (itemWidth + sepSize) >= itemWidth)
    		++itemsPerLine;
    	int i = 0;
    	itemWidth += sepSize;
    	for (Object v : values) {
    		if (i > 0 && i % itemsPerLine == 0)
    			println();
    		print(leftFlush(itemWidth, v));
    		++i;
    	}
    	if (i % itemsPerLine != 1)
    		println();
    }

    protected static JTextArea jTextArea = null;

    public static void createAndShowGUI() {
/*
        // Determine which fonts support Chinese here ...
        ArrayList<Font> chinesefonts = new ArrayList<Font>();
		Font[] allfonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
		int fontcount = 0;
		String chinesesample = "\u4e00";
		for (int j = 0; j < allfonts.length; j++) {
	    	if (allfonts[j].canDisplayUpTo(chinesesample) == -1)
	        	chinesefonts.add(allfonts[j]);
  	    	fontcount++;
		}
*/
        JFrame frame = new JFrame("Test Console");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jTextArea= new JTextArea("");
        jTextArea.setFont(new java.awt.Font("MS Song", Font.BOLD, 14));
        frame.getContentPane().add(jTextArea);
        frame.setMinimumSize(new Dimension(200, 650));
        frame.pack();
        frame.setVisible(true);
    }
}
